﻿using System;
using System.Configuration;
using Eswat.Configuration;
using Microsoft.Practices.ServiceLocation;

namespace Eswat
{
	/// <summary>
	/// 
	/// </summary>
	public static class DependencyManager
	{
		/// <summary>
		/// Loads from configuration.
		/// </summary>
		/// <param name="registerServiceAction">The register service action.</param>
		/// <param name="registerTestResultLoggingServiceAction">The register test result logging service action.</param>
		public static void LoadFromConfiguration(
			Action<ITestService> registerServiceAction,
			Action<ITestResultLoggingService> registerTestResultLoggingServiceAction)
		{
			var config = (EswatConfiguration)ConfigurationManager.GetSection("eswat");

			RegisterDependency(config.TestResultsLoggingType, registerTestResultLoggingServiceAction);

			foreach (ServiceConfigurationElement serviceConfig in config.Services)
			{
				RegisterDependency(serviceConfig.Name, serviceConfig.Type, registerServiceAction);
			}
		}

		/// <summary>
		/// Registers the dependency.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="type">The type.</param>
		/// <param name="registrationAction">The registration action.</param>
		/// <returns></returns>
		private static ITestService RegisterDependency(
			string name,
			string type,
			Action<ITestService> registrationAction)
		{
			var serviceType = Type.GetType(type);

			if (serviceType == null) throw new TypeLoadException(string.Format("Unrecognized ESWAT service {0} of type {1}", name, type));

			var serviceTypeInstance = Activator.CreateInstance(serviceType, name);

			if (serviceTypeInstance == null) throw new ActivationException(string.Format("Failed to initialize ESWAT service {0} of type {1}", name, type));

			var serviceInstance = (ITestService)serviceTypeInstance;

			if (serviceInstance == null) throw new InvalidCastException(string.Format("ESWAT service {0} was not a valid ITestService. The type {1} does not implement the expected ITestService interface.", name, type));

			registrationAction(serviceInstance);

			return serviceInstance;
		}

		/// <summary>
		/// Registers the dependency.
		/// </summary>
		/// <param name="type">The type.</param>
		/// <param name="registrationAction">The registration action.</param>
		/// <returns></returns>
		private static ITestResultLoggingService RegisterDependency(
			string type,
			Action<ITestResultLoggingService> registrationAction)
		{
			var serviceType = Type.GetType(type);

			if (serviceType == null) throw new TypeLoadException(string.Format("Unrecognized ESWAT test results logging service of type {0}", type));

			var serviceTypeInstance = Activator.CreateInstance(serviceType);

			if (serviceTypeInstance == null) throw new ActivationException(string.Format("Failed to initialize ESWAT test results logging service of type {0}", type));

			var serviceInstance = (ITestResultLoggingService)serviceTypeInstance;

			if (serviceInstance == null) throw new InvalidCastException(string.Format("ESWAT test results logging service {0} was not a valid ITestResultLoggingService. The type {0} does not implement the expected ITestResultLoggingService interface.", type));

			registrationAction(serviceInstance);

			return serviceInstance;
		}
	}
}
